<template>
  <el-form
    ref="ruleFormRef"
    :model="ruleForm"
    :rules="rules"
    label-width="120px"
    class="demo-ruleForm"
    :class="{fhlw:config?.horizontallyWidth}"
    :size="formSize"
  >
    <el-form-item
      v-for="(items,index) in formList"
      :key="items.prop"
      :label="items.label"
      :prop="items.prop"
      :style="items.importantStyle||config?.horizontallyWidth"
    >
      <el-col :span="(config?.horizontallyWidth&&24)||items.span||24">
        <template v-if="items.type==='input'">
          <el-input
            v-model="ruleForm[items.prop]"
            :placeholder="items.placeholder"
          />
        </template>
        <template v-if="items.type==='select'&&items.option">
          <el-select
            v-model="ruleForm[items.prop]"
            :disabled="items.disabled"
            :multiple="items.multiple"
            :collapse-tags="items.collapseTags"
            :filterable="items.isSearch"
            :remote="items.isSearch"
            :reserve-keyword="items.isSearch"
            :placeholder="items.placeholder"
            :remote-method="(query:string)=>{remoteMethod(query, items.option, index)}"
            clearable
            @clear="selectChange(index)"
            :style="items.style"
          >
            <el-option
              v-for="item in items.option"
              :key="item.label"
              :label="item.label"
              :value="item.value"
              :disabled="item.disabled"
            />
          </el-select>
        </template>
        <template v-if="items.type==='date'">
          <el-date-picker
            v-model="ruleForm[items.prop]"
            type="date"
            :format="items.format||'YYYY-MM-DD'"
            :value-format="items.valueFormat||'YYYY-MM-DD'"
            :placeholder="items.placeholder"
            :style="items.style"
            :disabled-date="(time:Date)=>disabledDate(time, items.disabledTime)"
          />
        </template>
        <template v-if="items.type==='switch'">
          <el-switch v-model="ruleForm[items.prop]" />
        </template>
        <template v-if="items.type==='checkbox'">
          <el-checkbox-group v-model="ruleForm[items.prop]">
            <el-checkbox
              v-for="item in items.checkBoxOption"
              :key="item.name"
              :label="item.label"
              :name="item.name"
            />
          </el-checkbox-group>
        </template>
        <template v-if="items.type==='radio'">
          <el-radio-group v-model="ruleForm[items.prop]">
            <el-radio
              v-for="item in items.option"
              :key="item.label"
              :label="item.label"
            >
              {{ item.value }}
            </el-radio>
          </el-radio-group>
        </template>
        <template v-if="items.type==='textarea'">
          <el-input
            v-model="ruleForm[items.prop]"
            type="textarea"
          />
        </template>
      </el-col>
    </el-form-item>
    <el-form-item class="flr">
      <el-button
        type="primary"
        @click="submitForm(ruleFormRef)"
      >
        {{ btnText||'Create' }}
      </el-button>
      <el-button @click="resetForm(ruleFormRef)">
        Reset
      </el-button>
    </el-form-item>
  </el-form>
</template>

<script lang="ts" setup>
import type { ElForm } from 'element-plus'
import moment from 'moment'
type FormInstance = InstanceType<typeof ElForm>

const formSize = ref('')
const ruleFormRef = ref<FormInstance>()

interface Option{
  label: string
  value: string
  disabled?: Boolean
}
interface CheckBoxOption{
  label: string
  name: string
  disabled?: Boolean
}
interface DisabledTime{
  start?:string
  during?: string[]
  end?:string
}
interface FormList{
  prop: string
  label: string
  type: string
  placeholder?: string
  style?: string
  option?:Option[]
  importantStyle:string
  checkBoxOption?:CheckBoxOption[]
  span?: Number
  disabled?: Boolean
  multiple?: Boolean
  collapseTags?: Boolean
  isSearch?: Boolean
  format?: string
  valueFormat?: string
  disabledTime?:DisabledTime
}
interface RulesItem{
  message: string
  trigger: string
  required?: boolean
  min?: Number
  max?: Number
}
interface RulesITF{
  [propName: string]:RulesItem[]
}
interface SelectList{
  [propName: number]:Option[]
}
interface FormData{
  [propName: string]:any
}

interface Config{
  horizontallyWidth?:string
  disabledTime?:DisabledTime
}
interface Props {
  formList: FormList[]
  rules: RulesITF
  formData: FormData
  btnText: string
  config?: Config
}

const emit = defineEmits(['submitData', 'update:formData', 'update:formList'])
const props = defineProps<Props>()
const { formList, rules, formData: ruleForm, btnText, config } = toRefs(reactive({
  ...props
}))

const loading = ref(false)
const selectList = ref<SelectList>({})

// formData和父组件数据同步
watchEffect(() => emit('update:formData', ruleForm.value))
// 提交
const submitForm = (formEl: FormInstance | undefined) => {
  console.log(ruleForm.value)
  if (!formEl) return
  formEl.validate((valid) => {
    if (valid) {
      emit('submitData', ruleForm.value)
    } else {
      console.log('error submit!')
      return false
    }
  })
}
// 重置
const resetForm = (formEl: FormInstance | undefined) => {
  if (!formEl) return
  formEl.resetFields()
}
// 获取原始select option值
for (const [index, item] of formList.value.entries()) {
  if (item.type === 'select') {
    Object.assign(selectList.value, {
      [index]: item.option
    })
  }
}
// 远程搜索
// 注意：搜索选择以后再次搜索，搜索的列表是以上次搜索结果为范围的，如果要以全部的搜索结果来为范围将option改为selectList.value[index]
const remoteMethod = (query: string, option:Option[]|undefined, index: number) => {
  if (query) {
    loading.value = true
    setTimeout(() => {
      loading.value = false
      const op = selectList.value[index]?.filter((item: { label: string; }) => {
        return item.label.toLowerCase().indexOf(query.toLowerCase()) > -1
      })
      formList.value[index].option = op
    }, 200)
  } else {
    formList.value[index].option = selectList.value[index]
  }
}
// 下拉框清除按钮显示原始的option内容
const selectChange = (index:number) => {
  formList.value[index].option = selectList.value[index]
}

// 时间选择器设置时间范围
const disabledDate = (time: Date, disabledTime?:DisabledTime) => {
  if (!disabledTime) return
  const { start, during, end } = disabledTime
  // const traverseDate = time.getTime()
  // 不要用moment(new Date(start)).valueOf()和traverseDate进行对比，traverseDate是以0点计算，moment是以8点计算
  // moment(itemTime).diff(moment(traverseDate), 'days')也不行，同理
  const format = 'YYYYMMDD'
  const traverseDate = moment(time).format(format)
  let flag = false
  if (start) { // 开始时间
    flag = moment(new Date(start)).format(format) > traverseDate
  }
  if (during?.length && !flag) { // 某些时间禁用
    flag = !!during.find(item => traverseDate === moment(new Date(item)).format(format))
  }
  if (end && !flag) { // 结束时间
    flag = moment(new Date(end)).format(format) < traverseDate
  }
  return flag
}

</script>
